package com.hzw.saas.api.old.storage.bo;

import java.io.Serializable;
import java.util.*;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.hzw.saas.api.old.storage.constants.StatusString;
import com.hzw.saas.api.storage.enums.FileIntegrityEnum;
import com.hzw.saas.api.storage.enums.ResourceStatusEnum;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.util.constants.PatternConsts;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import org.springframework.format.annotation.DateTimeFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * 资源信息
 *
 * @author zzl
 * @since 12/24/2020
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
// @ApiModel("(旧版)资源文件")
public class ResourceFileBO implements Serializable {

    private static final long serialVersionUID = -8828838318925676884L;

    /**
     * ID
     */
    @ApiModelProperty(value = "文件唯一ID", position = 1, required = true)
    private String fileId;

    /**
     * 文件所在目录ID，根目录ID为0
     */
    @ApiModelProperty(value = "目录ID(根目录ID为0)", position = 2)
    private String folderId;

    /**
     * 文件完整名称，含后缀
     */
    @ApiModelProperty(value = "文件完整名称(含后缀)", position = 3)
    private String name;

    /**
     * 文件后缀
     */
    @ApiModelProperty(value = "文件后缀", position = 4)
    private String suffix;

    /**
     * 文件长度，单位：byte
     */
    @ApiModelProperty(value = "文件长度(单位：byte)", position = 5)
    private Long length;

    /**
     * 文件摘要，MD5
     */
    @ApiModelProperty(value = "文件摘要(MD5)", position = 6)
    private String digest;

    /**
     * 文件完整性
     *
     * @see FileIntegrityEnum
     */
    @ApiModelProperty(value = "文件完整性, " + StatusString.FILE_INTEGRITY, position = 7)
    private Integer integrity;

    /**
     * 文件状态
     *
     * @see ResourceStatusEnum
     */
    @ApiModelProperty(value = "文件状态, " + StatusString.RESOURCE_STATUS, position = 8)
    private Integer status;

    /**
     * 存储虚拟目录
     */
    @ApiModelProperty(value = "存储虚拟目录", position = 11)
    private String catalog;

    /**
     * 存储类型
     */
    @ApiModelProperty(value = "存储类型", position = 9)
    private String serviceType;

    /**
     * 存储名称
     */
    @ApiModelProperty(value = "存储名称", position = 10)
    private String serviceProvider;

    /**
     * 资源路径
     */
    @ApiModelProperty(value = "资源路径", position = 12)
    private String url;

    /**
     * 资源存储Key
     */
    @ApiModelProperty(value = "资源存储Key", position = 13)
    private String resourceKey;

    /**
     * 创建者ID
     */
    @ApiModelProperty(value = "创建者ID", position = 14)
    private String creatorId;

    /**
     * 创建者名称
     */
    @ApiModelProperty(value = "创建者名称", position = 15)
    private String creatorName;

    /**
     * 所有者ID（用户或共享空间）
     */
    @ApiModelProperty(value = "所有者ID", position = 16)
    private String ownerId;

    /**
     * 所有者名称
     */
    @ApiModelProperty(value = "所有者名称", position = 17)
    private String ownerName;

    /**
     * 创建时间
     */
    @ApiModelProperty(value = "创建时间, format=" + PatternConsts.NORM_DATETIME_PATTERN, position = 18)
    @DateTimeFormat(pattern = PatternConsts.NORM_DATETIME_PATTERN)
    @JsonFormat(pattern = PatternConsts.NORM_DATETIME_PATTERN)
    private Date createDate;

    /**
     * 更新时间
     */
    @ApiModelProperty(value = "更新时间, format=" + PatternConsts.NORM_DATETIME_PATTERN, position = 19)
    @DateTimeFormat(pattern = PatternConsts.NORM_DATETIME_PATTERN)
    @JsonFormat(pattern = PatternConsts.NORM_DATETIME_PATTERN)
    private Date updateDate;

    /**
     * 文件分片信息,JSON数组转Base64
     *
     * @see LocChunkBO
     */
    private String chunkInfo;

    /**
     * 共享的群组
     */
    @ApiModelProperty(value = "共享群组ID列表", position = 15)
    private List<String> groupIds = new ArrayList<>();

    /**
     * 增加分享的群组id
     *
     * @param groupIds 分享的群组ID
     * @return 群组列表
     */
    public void addGroupIds(String... groupIds) {
        if (this.groupIds == null) {
            this.groupIds = new ArrayList<>();
        }
        this.groupIds.addAll(Arrays.asList(groupIds));
    }

    /**
     * 清空群组列表
     */
    public void emptyGroupIds() {
        if (this.groupIds == null) {
            this.groupIds = new ArrayList<>();
        }
        this.groupIds.clear();
    }

    /**
     * 设置已上传分片信息列表
     *
     * @param fileChunkBOList
     */
    public void uploadedChunks(List<LocChunkBO> fileChunkBOList) {
        if (fileChunkBOList == null)
            return;
        this.setChunkInfo(Base64.encode(JSONUtil.toJsonStr(fileChunkBOList)));
    }

    /**
     * 获取已上传的分片列表
     *
     * @return
     */
    public List<LocChunkBO> uploadedChunks() {
        if (StringUtils.isBlank(this.getChunkInfo()))
            return new ArrayList<>();
        return JSONUtil.toList(Base64.decodeStr(this.getChunkInfo()), LocChunkBO.class);
    }

    /**
     * 获取指定ID的分片列表
     *
     * @param idList
     * @return
     */
    public List<LocChunkBO> filterUploadedChunks(List<String> idList) {
        if (idList == null || idList.size() == 0)
            return new ArrayList<>();
        List<LocChunkBO> uploadedChunks = this.uploadedChunks();
        List<LocChunkBO> resultList = new ArrayList<>();
        idList.removeIf(id -> {
            if (StrUtil.isBlank(id))
                return true;
            LocChunkBO result = uploadedChunks.stream()
                .filter(fileChunkBO -> Objects.equals(fileChunkBO.getChunkId(), id))
                .findAny().orElse(null);
            if (result != null) {
                resultList.add(result);
                return true;
            }
            return false;
        });
        AssertUtil.assertThrow("以下分片不存在(id)：" + JSONUtil.toJsonStr(idList), idList.size() != 0);
        return resultList;
    }

    /**
     * 增加已上传分片信息
     *
     * @param fileChunkBOList
     * @return
     */
    public ResourceFileBO addUploadedChunks(List<LocChunkBO> fileChunkBOList) {
        if (fileChunkBOList == null)
            return this;
        List<LocChunkBO> uploadedChunks = this.uploadedChunks();
        uploadedChunks.addAll(fileChunkBOList);
        this.uploadedChunks(uploadedChunks);
        return this;
    }

    /**
     * 增加已上传分片信息
     *
     * @param fileChunkBO
     * @return
     */
    public ResourceFileBO addUploadedChunk(LocChunkBO fileChunkBO) {
        if (fileChunkBO == null)
            return this;
        List<LocChunkBO> uploadedChunks = this.uploadedChunks();
        uploadedChunks.add(fileChunkBO);
        this.uploadedChunks(uploadedChunks);
        return this;
    }

    /**
     * 删除分片信息
     *
     * @param chunkIdList
     * @return
     */
    public ResourceFileBO deleteUploadedChunks(List<String> chunkIdList) {
        if (chunkIdList == null) {
            return this;
        }
        List<LocChunkBO> uploadedChunks = this.uploadedChunks();
        uploadedChunks.removeIf(next -> chunkIdList.contains(next.getChunkId()));
        this.uploadedChunks(uploadedChunks);
        return this;
    }

    /**
     * 删除分片信息
     *
     * @param chunkId
     * @return
     */
    public ResourceFileBO deleteUploadedChunk(String chunkId) {
        List<String> idList = CollectionUtil.list(false, chunkId);
        this.deleteUploadedChunks(idList);
        return this;
    }

    public ResourceFileBO deleteAllChunks() {
        this.uploadedChunks(new ArrayList<>());
        return this;
    }
}
